<template>
  <el-config-provider :locale="zhCn">
    <div
      class="tu-main"
      id="tu-main"
    >
      <div
        v-if="searchOption?.immediate"
        class="tu-search-content"
        id="tu-search"
      >
        <SearchIndex
          ref="searchRef"
          :search-list="searchList"
          @search-click="formSearch"
        />
      </div>
      <div
        :style="{ height: tableBoxHeight }"
        class="tu-table-content"
      >
        <div
          v-if="tableOption?.hiddenSlot !== false"
          id="tu-slot"
          class="tu-slot"
        >
          <div>
            <slot></slot>
          </div>
          <Toolbar
            v-if="tableOption?.hiddenToolbar !== false"
            ref="toolbarRef"
            :table-header="tableColumns"
            :activeIds="activeTreeIds"
            @refreshData="searchData"
            @updateTableColumn="updateTableColumn"
          />
        </div>
        <div>
          <TuTable
            ref="tableRef"
            :table-header="tableHeaders"
            :table-option="tableOption"
            :pagination-option="paginationOption"
            :slotNames="slotNames"
          >
            <template
              v-if="tableOption?.expand"
              #expand="{ row, index }"
            >
              <slot
                name="expand"
                :row
                :index="index"
              />
            </template>
            <template
              v-for="slotItem in slotNames"
              :key="slotItem"
              #[slotItem]="{ row, index }"
            >
              <slot
                :name="slotItem"
                :index
                :row
              ></slot>
            </template>
          </TuTable>
        </div>
        <div
          v-if="paginationOption?.hidden !== false"
          class="tu-paging"
          id="tu-paging"
        >
          <pagination
            ref="paginationRef"
            :pagination-option="paginationOption"
            @search="searchData"
          />
        </div>
      </div>
    </div>
  </el-config-provider>
</template>

<script lang='ts' setup>
import { nextTick, onMounted, ref } from 'vue';
import type { SearchItemType, SearchOptionType, tableHeaderType, tableOptionType, paginationType } from './TableType';
import SearchIndex from './search/SearchIndex.vue';
import Toolbar from './toolbar/Toolbar.vue'
import TuTable from './table/TuTable.vue';
import pagination from './pagination/pagination.vue';
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'

const props = withDefaults(defineProps<{
  searchList?: SearchItemType[]
  searchOption?: SearchOptionType
  tableHeader?: tableHeaderType[]
  tableOption?: tableOptionType
  paginationOption?: paginationType
}>(), {
  searchList: () => [],
  searchOption: () => ({ immediate: true, heidden: true }),
  tableHeader: () => [],
  tableOption: () => ({}),
  paginationOption: () => ({}),
})

const emits = defineEmits<{
  (e: 'searchData', formData: any, isRest: boolean): void
}>()

const tableRef = ref()

// 基础数据
const tableColumns = ref<tableHeaderType[]>([])
// 获取当前时间戳
const nowTime = new Date().getTime()
// 初始显示的表头Id
const activeTreeIds = ref<string[]>([])

/**
 * 初始化id
 * @param columns 表头列表
 * @param level 层级
 */
const initColumns = (columns: tableHeaderType[], level: number = 1) => {
  let arr: tableHeaderType[] = []

  columns.forEach((item, index) => {
    if (item?.heidden !== false) {
      activeTreeIds.value.push(nowTime.toString() + level + index)
    }
    if (item?.children) {
      let arr2 = initColumns(item.children, level + 1)
      item.children = arr2
      arr.push({
        id: nowTime.toString() + level + index,
        ...item,
        column: item?.column ?? {}
      })
    } else {
      arr.push({
        id: nowTime.toString() + level + index,
        ...item,
        column: item?.column ?? {}
      })
    }
  })

  return arr
}
tableColumns.value = initColumns(props.tableHeader)

// 动态插槽名称
const slotNames = ref<string[]>([])

/**
 * 初始化表格头部数据
 * @param columns 表头列表
 * @param level 层级
 * @param heiddenIds 指定显示的表头id列表
 */
const initTableColumns = (columns: tableHeaderType[], level: number = 1, heiddenIds?: string[]) => {
  let arr: tableHeaderType[] = []

  columns.forEach(item => {
    // 如果传第三个参数，则以第三个参数显示优先
    if (heiddenIds?.length) {
      if (heiddenIds.findIndex(id => id === item?.id) !== -1) {
        if (item?.children) {
          let arr2 = initTableColumns(item.children, level + 1, heiddenIds)
          item.children = arr2
          arr.push(item)
        } else {
          if (item?.slotName) {
            slotNames.value.push(item.slotName)
          }
          arr.push(item)
        }
      }
    } else if (item?.heidden !== false) {
      if (item?.children) {
        let arr2 = initTableColumns(item.children, level + 1)
        item.children = arr2
        arr.push(item)
      } else {
        if (item?.slotName) {
          slotNames.value.push(item.slotName)
        }
        arr.push(item)
      }
    }
  })

  return arr
}

// 表格头部数据
const tableHeaders = ref<tableHeaderType[]>([])
// 初始化赋值
tableHeaders.value = initTableColumns(JSON.parse(JSON.stringify(tableColumns.value)))

// 搜索表单对象
const searchRef = ref()

// 表格容器高度
const tableBoxHeight = ref("auto")

/**
 * 更新表格高度
 */
const upTableHeight = () => {
  // 获取主容器高度
  const mainBoxHeight = document.getElementById('tu-main')?.offsetHeight ?? 0
  const mainBoxWidth = document.getElementById('tu-main')?.offsetWidth ?? 0

  // 更新搜索条件排版
  if (mainBoxWidth < 640) {
    // 更新搜索组件单个span的占比
    searchRef.value.upDateItemSpan(24)
    // 更新表格高度
    // xxx
  } else if (mainBoxWidth > 640 && mainBoxWidth < 940) {
    searchRef.value.upDateItemSpan(12)
  } else if (mainBoxWidth > 940 && mainBoxWidth < 1240) {
    searchRef.value.upDateItemSpan(8)
  } else {
    searchRef.value.upDateItemSpan(6)
  }

  // (上面更新span之后，此处需要考略渲染速度)
  nextTick(() => {
    // 获取搜索组件容器高度
    const searchBoxHeight = document.getElementById('tu-search')?.offsetHeight ?? 0
    // 高度 = 主容器高度 - 搜索组件高度 - 搜索组件下边距 - 表格容器内边距
    const result = mainBoxHeight - searchBoxHeight - 10 - 20
    if (result > 0) {
      // 更新表格容器高度
      tableBoxHeight.value = result + 'px'
      // 获取插槽高度
      const slotBox = document.getElementById('tu-slot')?.offsetHeight ?? 0
      // 获取分页容器高度
      const pagingBox = document.getElementById('tu-paging')?.offsetHeight ?? 0
      // 更新表格高度
      tableRef.value.setTableHeight(result - (slotBox ? (slotBox + 10) : 0) - (pagingBox ? (pagingBox + 10) : 0))
    }
  })
}

const mergeParams = () => {
  let params: any = {}
  if (searchRef.value) {
    params = { ...searchRef.value?.formData }
  }
  if (paginationRef.value) {
    params = {
      ...params,
      limit: paginationRef.value.limit,
      page: paginationRef.value.page
    }
  }
  return params
}

/**
 * 搜索点击
 * @param isReset 是否重置触发
 */
const formSearch = (isReset: boolean) => {
  emits('searchData', mergeParams(), isReset)
}

/**
 * 分页搜索,工具栏刷新
 */
const searchData = () => {
  emits('searchData', mergeParams(), false)
}

/**
 * 通过id返回层级下标数组
 * @param columnList 查找列表
 * @param columnId 表头ID
 */
const findColumnIndex = (columnList: tableHeaderType[] = [], columnId: string) => {
  let idIndexs: number[] = []

  for (let i = 0; i < columnList.length; i++) {
    if (columnList[i]?.children?.length) {
      const idArr = findColumnIndex(columnList[i]?.children, columnId)
      if (idArr?.length) {
        idIndexs.push(...[i, ...idArr])
      }
    } else if (columnList[i]?.id === columnId) {
      idIndexs.push(i)
      break
    }
  }

  return idIndexs
}

/**
 * 删除指定下标的元素
 * @param indexs 下标数组
 */
const parentEmpty = (indexs: number[]) => {

  if (indexs.length === 1) {
    // 非多级表头
    // 删除表头
    tableHeaders.value.splice(indexs[0], 1)
  } else {
    // 多级表头
    // 初始化表头
    let columnItem: tableHeaderType | null = null

    for (let i = 0; i < indexs.length; i++) {
      if (i === indexs.length - 1 && columnItem) {
        if (columnItem.children?.length === 1) {
          let indexCopy = [...indexs]
          // 如果该节点下级只有一个，那么当前节点也应该同时删除
          // 删除最后一个，再执行一遍
          // 当所有子节点都消失后，隐藏父级结点
          indexCopy.pop()
          parentEmpty(indexCopy)
        } else {
          columnItem.children?.splice(indexs[i], 1)
        }
      } else {
        columnItem = tableHeaders.value[indexs[i]]
      }
    }
  }
}

// 工具栏实例
const toolbarRef = ref()

/**
 * 工具栏筛选表头
 * @param columnId 结点
 * @param heidden 是否显示
 * @param heiddenIds 主动传入显示的表头数组
 */
const updateTableColumn = (columnId: string, heidden: boolean, heiddenIds: string[] = []) => {
  if (heidden) {
    // 显示
    // 重新赋值，Vue 的算法会自动更新变动的数据
    tableHeaders.value = initTableColumns(
      JSON.parse(JSON.stringify(tableColumns.value)),
      1,
      heiddenIds?.length ? heiddenIds : toolbarRef.value.getCheckedKeys()
    )
  } else {
    // 隐藏
    const idList = findColumnIndex(tableHeaders.value, columnId)
    if (idList?.length) {
      parentEmpty(idList)
    }
  }
}

/**
 * 设置表头显示状态
 * @param prop 表头绑定属性
 * @param hidden 是否显示
 */
const setColumHidden = (prop: string, hidden: boolean) => {
  const columnId = tableColumns.value.find(item => item?.prop === prop)?.id
  if (columnId) {
    if (hidden) {
      activeTreeIds.value.push(columnId)
    } else {
      const columnIndex = activeTreeIds.value.findIndex(item => item === prop)
      if (columnIndex !== -1) {
        activeTreeIds.value.splice(columnIndex, 1)
      }
    }
    updateTableColumn(columnId, hidden, activeTreeIds.value)
    // 更新工具栏状态
    toolbarRef.value?.setChecked(columnId)
  }
}

const paginationRef = ref()

/**
 * 设置表格数据
 * @param data 数据
 * @param total 总数
 */
const setData = <T>(data: T, total: number = 0) => {
  tableRef.value.setTableData(data)
  paginationRef.value.setTotal(total)

  // 如果分页存在，更新表格的序号参数
  if (paginationRef.value) {
    tableRef.value.setPagination(paginationRef.value.page, paginationRef.value.limit)
  }
}

onMounted(() => {
  // 初始化表格高度
  // 如果主动传入了表格高度，则无需初始化表格高度
  if (!props.tableOption?.tableHeight) {
    upTableHeight()

    // 监听窗口大小变化
    window.addEventListener('resize', () => {
      upTableHeight()
    })
  } else {
    tableRef.value.setTableHeight(props.tableOption.tableHeight)
  }

  if (props.searchOption?.immediate !== false) {
    // 初始化查询
    searchData()
  }
})

/**
 * 获取表格数据
 */
const getTableData = () => {
  return tableRef.value?.getTableData()
}

/**
 * 获取表格实例
 */
const getTableInstance = () => {
  return tableRef.value?.getTableInstance()
}

/**
 * 设置查询条件
 * @param data 对象
 * @param immediate 设置完后是否执行查询
 * @param isRest 设置前是否重置搜索条件
 */
const setSearchData = <T>(data: T, immediate: boolean = false, isRest?: boolean) => {
  searchRef.value?.setSearchData(data, immediate, isRest)
}

/**
 * 设置下拉框数据
 * @param prop 搜索条件绑定的属性名
 * @param list 下拉列表
 */
const setDropDown = (prop: string, list: any[]) => {
  searchRef.value?.setDropDown(prop, list)
}

defineExpose({
  setData,
  getSearchDate: () => searchRef.value?.formData,
  setSearchHidden: (prop: string, heidden: boolean) => searchRef.value?.setSearchHidden(prop, heidden),
  setColumHidden,
  getTableData,
  getTableInstance,
  setSearchData,
  setDropDown
})
</script>

<style scoped lang='scss'>
.tu-main {
  height: 100%;
  min-height: 400px;

  .tu-search-content {
    background-color: #FFF;
    border-radius: 4px;
    padding: 10px;
    margin-bottom: 10px;
  }

  .tu-table-content {
    background-color: #FFF;
    border-radius: 4px;
    padding: 10px;
    overflow: hidden;

    .tu-slot {
      display: flex;
      justify-content: space-between;
      margin-bottom: 10px;
    }

    .tu-paging {
      margin-top: 10px;

      :deep(.el-pagination) {
        justify-content: end;
      }
    }
  }


}
</style>